package com.iwdnb.gkgz.common.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.iwdnb.bmnf.common.utils.HttpClientUtils;
import com.iwdnb.gkgz.common.enums.RangeTypeEnums;
import com.iwdnb.gkgz.common.enums.StockSecondIndustryEnums;
import com.iwdnb.gkgz.common.model.dto.Stock;
import com.iwdnb.gkgz.common.model.dto.StockAnalasysData;
import com.iwdnb.gkgz.common.model.dto.StockAnalasysData.ScoreData;
import com.iwdnb.gkgz.common.model.dto.StockDayData;
import com.iwdnb.gkgz.common.model.dto.StockMinuteData;
import com.iwdnb.gkgz.common.model.dto.StockRangeScopeDTO;
import com.iwdnb.gkgz.common.quota.BollingerBands.BollingerData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import static cn.hutool.core.date.DatePattern.PURE_DATETIME_PATTERN;

@Slf4j
public class StockUtils {
    public static final Map<String, Stock> STOCK_MAP = new ConcurrentHashMap<>();
    public static final List<String> SECOND_INDUSTRY_BLACK_LIST = new ArrayList<>();

    public static String getSimpleCode(String code) {
        return code.substring(2);
    }

    public static List<String> formatStockCodes(List<Stock> stockList) {
        return stockList.stream()
            .map(stock -> stock.getCode()).collect(Collectors.toList());
    }

    //public static void getRealtimeData(String code) {
    //    //HttpClient client = HttpClient.newHttpClient();
    //    //HttpRequest request = HttpRequest.newBuilder(URI.create(""))
    //    //    .setHeader("Referer", "https://finance.sina.com.cn")
    //    //    .build();
    //    //HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    //    //String body = response.body();
    //    String url = "https://hq.sinajs.cn/list=" + code;
    //    String body = HttpClientUtils.get(url);
    //    //HttpHeaders headers = new HttpHeaders();
    //    //headers.setContentType(MediaType.APPLICATION_JSON);
    //    //headers.set("Referer", "https://finance.sina.com.cn");
    //    //
    //    //HttpEntity entity = new HttpEntity<>(headers);
    //    //
    //    //ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
    //    //String body = response.getBody().toString();
    //    String[] infoStrings = body.split("\"");
    //    String[] infoArray = infoStrings[1].split(",");
    //    String name = infoArray[0];
    //    double price = Double.valueOf(infoArray[3]);
    //    double price_pre = Double.valueOf(infoArray[2]);
    //    String date = infoArray[30];
    //    String time = infoArray[31];
    //    System.out.println(body);
    //    System.out.println(date);
    //}
    public static StockDayData getStockDayData(List<StockDayData> stockDayDataList, String date) {
        if (CollectionUtils.isEmpty(stockDayDataList)) {
            return null;
        }
        return stockDayDataList.stream().filter(stockDayData -> stockDayData.getDate().equals(date)).findAny().orElse(
            null);
    }

    public static StockDayData getStockDayDataBeforeDate(
        List<StockDayData> stockDayDataList, String dateStr, int size) {
        Date date = DateUtil.parseDate(dateStr);
        stockDayDataList = stockDayDataList.stream()
            .filter(stockDayData -> DateUtil.parseDate(stockDayData.getDate()).before(date))
            .collect(Collectors.toList());
        if (size >= stockDayDataList.size()) {
            return null;
        }
        return stockDayDataList.get(stockDayDataList.size() - size);
    }

    /**
     * 计算涨跌幅
     *
     * @param stockDayDataList
     */
    public static void calculateStockRange(List<StockDayData> stockDayDataList) {
        if (CollectionUtils.isEmpty(stockDayDataList)) {
            return;
        }
        BigDecimal yesterdayClosePrice = stockDayDataList.get(0).getOpenPrice();
        for (StockDayData data : stockDayDataList) {
            BigDecimal dateRate = BigDecimalUtils.subStractAndDividePrecent(data.getClosePrice(), yesterdayClosePrice);
            data.setBeforeClosePrice(yesterdayClosePrice);
            data.setRate(dateRate);
            BigDecimal highPrice = BigDecimalUtils.isGt(dateRate, BigDecimal.ZERO) ? data.getClosePrice()
                : data.getOpenPrice();
            data.setHighRate(BigDecimalUtils.subStractAndDividePrecent(data.getMaxPrice(), highPrice));
            BigDecimal lowPrice = BigDecimalUtils.isGt(dateRate, BigDecimal.ZERO) ? data.getOpenPrice()
                : data.getClosePrice();
            data.setLowRate(BigDecimalUtils.subStractAndDividePrecent(data.getMinPrice(), lowPrice));
            yesterdayClosePrice = data.getClosePrice();
        }
    }

    public static List<StockDayData> getStockDayDataListByDateRange(List<StockDayData> stockDayDataList,
        String beginStr, String endStr) {
        if (CollectionUtils.isEmpty(stockDayDataList)) {
            return null;
        }
        Date begin = DateUtil.parseDate(beginStr);
        Date end = DateUtil.parseDate(endStr);
        return stockDayDataList.stream().filter(stockDayData -> {
            Date date = DateUtil.parseDate(stockDayData.getDate());
            return DateUtils.afterOrEquals(date, begin) && DateUtils.beforeOrEquals(date, end);
        }).collect(Collectors.toList());
    }

    public static List<StockDayData> getStockDayDataListByDateRange(List<StockDayData> stockDayDataList, Date begin,
        Date end) {
        if (CollectionUtils.isEmpty(stockDayDataList)) {
            return null;
        }
        return stockDayDataList.stream().filter(stockDayData -> {
            Date date = DateUtil.parse(stockDayData.getDate());
            return DateUtils.afterOrEquals(date, begin) && DateUtils.beforeOrEquals(date, end);
        }).collect(Collectors.toList());
    }

    public static void sortStockDayDataList(List<StockDayData> stockDayDataList) {
        Collections.sort(stockDayDataList, (o1, o2) -> DateUtil.parseDate(o1.getDate())
            .before(DateUtil.parseDate(o2.getDate())) ? -1 : 1);

    }

    public static StockDayData getBeforedayStockDayData(List<StockDayData> stockDayDataList, String dateStr) {
        List<StockDayData> list = getStockDayDataListBeforeDate(stockDayDataList, dateStr, 1);
        return CollectionUtils.isNotEmpty(list) ? list.get(0) : null;
    }

    public static StockDayData getYesterdayStockDayData(List<StockDayData> stockDayDataList, String dateStr) {
        List<StockDayData> list = getStockDayDataListBeforeDate(stockDayDataList, dateStr, 1);
        return CollectionUtils.isNotEmpty(list) ? list.get(0) : null;
    }

    public static StockDayData getTomorrowStockDayData(List<StockDayData> stockDayDataList, String dateStr) {
        List<StockDayData> list = getStockDayDataListAfterDate(stockDayDataList, dateStr, 1);
        return CollectionUtils.isNotEmpty(list) ? list.get(0) : null;
    }

    public static List<StockDayData> getStockDayDataListBeforeDate(
        List<StockDayData> stockDayDataList, String dateStr, int size) {
        Date date = DateUtil.parseDate(dateStr);
        stockDayDataList = stockDayDataList.stream()
            .filter(stockDayData -> DateUtil.parseDate(stockDayData.getDate()).before(date))
            .collect(Collectors.toList());
        if (size >= stockDayDataList.size()) {
            return stockDayDataList;
        }
        return stockDayDataList.subList(stockDayDataList.size() - size, stockDayDataList.size());
    }

    public static List<StockDayData> getStockDayDataListAfterDate(
        List<StockDayData> stockDayDataList, String dateStr, int size) {
        if (CollectionUtils.isEmpty(stockDayDataList)) {
            return null;
        }
        Date date = DateUtil.endOfDay(DateUtil.parseDate(dateStr));
        stockDayDataList = stockDayDataList.stream()
            .filter(stockDayData -> DateUtil.parseDate(stockDayData.getDate()).after(date))
            .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(stockDayDataList)) {
            return stockDayDataList;
        }
        if (size >= stockDayDataList.size()) {
            return stockDayDataList;
        }
        if (stockDayDataList.size() < size) {
            return stockDayDataList;
        }
        return stockDayDataList.subList(0, size);
    }

    public static StockDayData getMaxPriceDataBeforeDate(List<StockDayData> stockDayDataList, String date, int size) {
        stockDayDataList = getStockDayDataListBeforeDate(stockDayDataList, date, size);
        BigDecimal max = stockDayDataList.get(0).getMaxPrice();
        StockDayData maxData = stockDayDataList.get(0);
        for (StockDayData data : stockDayDataList) {
            if (BigDecimalUtils.isGt(data.getMaxPrice(), max)) {
                max = data.getMaxPrice();
                maxData = data;
            }
        }
        return maxData;
    }

    public static BigDecimal getMaxPriceAfterDate(List<StockDayData> stockDayDataList, String date, int size) {
        return getMaxPriceDataAfterDate(stockDayDataList, date, size).getMaxPrice();
    }

    public static StockDayData getMaxPriceDataAfterDate(List<StockDayData> stockDayDataList, String date, int size) {
        stockDayDataList = getStockDayDataListAfterDate(stockDayDataList, date, size);
        return getMaxPriceData(stockDayDataList);
    }

    public static StockDayData getMaxPriceData(List<StockDayData> stockDayDataList) {
        if (CollectionUtils.isEmpty(stockDayDataList)) {
            return null;
        }
        BigDecimal max = stockDayDataList.get(0).getMaxPrice();
        StockDayData maxData = stockDayDataList.get(0);
        for (StockDayData data : stockDayDataList) {
            if (BigDecimalUtils.isGt(data.getMaxPrice(), max)) {
                max = data.getMaxPrice();
                maxData = data;
            }
        }
        return maxData;
    }

    public static BigDecimal getMaxPriceBeforeDate(List<StockDayData> stockDayDataList, String date, int size) {
        return getMaxPriceDataBeforeDate(stockDayDataList, date, size).getMaxPrice();
    }

    public static StockDayData getMinPriceDataBeforeDate(List<StockDayData> stockDayDataList, String date, int size) {
        stockDayDataList = getStockDayDataListBeforeDate(stockDayDataList, date, size);
        return getMinPriceData(stockDayDataList);
    }

    public static StockDayData getMinPriceData(List<StockDayData> stockDayDataList) {
        if (CollectionUtils.isEmpty(stockDayDataList)) {
            return null;
        }
        BigDecimal min = stockDayDataList.get(0).getMinPrice();
        StockDayData minData = stockDayDataList.get(0);
        for (StockDayData data : stockDayDataList) {
            if (BigDecimalUtils.isLt(data.getMinPrice(), min)) {
                min = data.getMinPrice();
                minData = data;
            }
        }
        return minData;
    }

    public static BigDecimal getMinPriceBeforeDate(List<StockDayData> stockDayDataList, String date, int size) {
        return getMinPriceDataBeforeDate(stockDayDataList, date, size).getMinPrice();
    }

    public static StockDayData getMinPriceDataAfterDate(List<StockDayData> stockDayDataList, String date, int size) {
        stockDayDataList = getStockDayDataListAfterDate(stockDayDataList, date, size);
        BigDecimal min = stockDayDataList.get(0).getMinPrice();
        StockDayData minData = stockDayDataList.get(0);
        for (StockDayData data : stockDayDataList) {
            if (BigDecimalUtils.isLt(data.getMinPrice(), min)) {
                min = data.getMinPrice();
                minData = data;
            }
        }
        return minData;
    }

    public static BigDecimal getMinPriceAfterDate(List<StockDayData> stockDayDataList, String date, int size) {
        return getMinPriceDataBeforeDate(stockDayDataList, date, size).getMinPrice();
    }

    public static StockRangeScopeDTO getRangeScopeByDateRange(List<StockDayData> list,
        String endDateStr) {
        String beginDate = DateUtil.formatDate(DateUtil.offsetDay(DateUtil.parseDate(endDateStr), -550));
        return getRangeScopeByDateRange(list, beginDate, endDateStr);
    }

    public static StockRangeScopeDTO getRangeScopeByDateRange(List<StockDayData> list,
        String beginDateStr, String endDateStr) {
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        list = getStockDayDataListByDateRange(list, beginDateStr, endDateStr);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        String lowDate = list.get(0).getDate();
        String highDate = list.get(0).getDate();
        BigDecimal highPrice = new BigDecimal(0);
        BigDecimal lowPrice = new BigDecimal(100000);

        for (StockDayData data : list) {

            BigDecimal price = data.getClosePrice();
            if (BigDecimalUtils.isLt(price, lowPrice)) {
                lowPrice = price;
                lowDate = data.getDate();
            }
            if (BigDecimalUtils.isGt(price, highPrice)) {
                highPrice = price;
                highDate = data.getDate();
            }

        }
        StockRangeScopeDTO rangeScopeDTO = new StockRangeScopeDTO();
        rangeScopeDTO.setLowPrice(lowPrice);
        rangeScopeDTO.setHighPrice(highPrice);
        rangeScopeDTO.setHighDate(highDate);
        rangeScopeDTO.setLowDate(lowDate);
        //高价日期在前，低价在后，说明当前日期是处于上升波段中
        boolean upFlag = DateUtil.parseDate(lowDate).after(DateUtil.parseDate(highDate));
        rangeScopeDTO.setRangeType(upFlag ? RangeTypeEnums.UP.getCode() : RangeTypeEnums.DOWN.getCode());
        return rangeScopeDTO;
    }

    public static StockRangeScopeDTO flatRangeScope(StockDayData stockDayData) {
        StockRangeScopeDTO rangeScopeDTO = new StockRangeScopeDTO();
        rangeScopeDTO.setLowPrice(stockDayData.getClosePrice());
        rangeScopeDTO.setHighPrice(stockDayData.getClosePrice());
        rangeScopeDTO.setHighDate(stockDayData.getDate());
        rangeScopeDTO.setLowDate(stockDayData.getDate());
        //持平
        rangeScopeDTO.setRangeType(RangeTypeEnums.STABLE.getCode());
        return rangeScopeDTO;
    }

    /**
     * 计算股票未来10天的最高收益
     *
     * @param code
     * @param date
     * @param stockDayDataList
     * @return
     */
    public static BigDecimal caculateAfterDaysProfit(String code, String date,
        List<StockDayData> stockDayDataList, int size) {
        StockDayData stockDayData = StockUtils.getStockDayData(stockDayDataList, date);
        if (Objects.isNull(stockDayData)) {
            stockDayData = stockDayDataList.get(0);
        }
        stockDayDataList = StockUtils.getStockDayDataListAfterDate(stockDayDataList, date, size);
        stockDayDataList.add(0, stockDayData);
        BigDecimal beginPrice = stockDayData.getClosePrice();
        BigDecimal maxPrice = BigDecimal.ZERO;
        BigDecimal minPrice = beginPrice;
        int maxIndex = 0;
        int minIndex = 0;
        for (int i = 0; i < stockDayDataList.size(); i++) {
            StockDayData data = stockDayDataList.get(i);
            if (BigDecimalUtils.isGt(data.getClosePrice(), maxPrice)) {
                maxPrice = data.getClosePrice();
                maxIndex = i;
            } else if (BigDecimalUtils.isLt(data.getClosePrice(), minPrice)) {
                minPrice = data.getClosePrice();
                minIndex = i;
            }
        }
        BigDecimal maxRate = BigDecimalUtils.subStractAndDividePrecent(maxPrice, beginPrice);
        BigDecimal minRate = BigDecimalUtils.subStractAndDividePrecent(minPrice, beginPrice);

        BigDecimal lastRate = BigDecimalUtils.subStractAndDividePrecent(
            stockDayDataList.get(stockDayDataList.size() - 1).getClosePrice(), beginPrice);

        log.debug(
            "{}-{}计算未来{}天的最高收益,maxPrice:{},maxRate:{},maxDayIndex:{},minPrice:{},minRate:{},minDayIndex:{},lastRate:{}",
            code, date, size, maxPrice, maxRate, maxIndex, minPrice, minRate, minIndex, lastRate);
        return maxRate;
    }

    public static List<StockDayData> getHistoryDataByYear(String code, String year) {
        return getHistoryData(code, year + "-01-01", year + "-12-31");
    }

    /**
     * @param code
     * @return
     */
    public static List<StockMinuteData> queryHistoryMinuteData(String code, List<Integer> periods) {
        List<StockMinuteData> list = new ArrayList<>();
        for (Integer period : periods) {
            list.addAll(queryHistoryMinuteData(code, period));
        }
        return list;
    }

    /**
     * 获取5、10、30、60分钟JSON数据；day日期、open开盘价、high最高价、low最低价、close收盘价、volume成交量；向前复权的数据。
     * 注意，最多只能获取最近的1023个数据节点。
     * eq:http://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData
     * .getKLineData?symbol=sz002095&scale=60&ma=no&datalen=1023
     *
     * @param code
     * @param period
     * @return
     */
    public static List<StockMinuteData> queryHistoryMinuteData(String code, int period) {
        String url = "https://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData"
            + ".getKLineData?symbol=%s&scale=%s&ma=no&datalen=1023";
        url = String.format(url, code, period);
        String body = HttpClientUtils.get(url);
        //HttpHeaders headers = new HttpHeaders();
        ////headers.setContentType(MediaType.APPLICATION_JSON);
        ////headers.set("Referer", "https://finance.sina.com.cn");
        //
        //HttpEntity entity = new HttpEntity<>(headers);
        //ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
        //String body = response.getBody().toString();
        JSONArray jsonArray = JSON.parseArray(body);
        List<StockMinuteData> list = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            StockMinuteData data = new StockMinuteData();
            data.setCode(code);
            Date date = DateUtil.parseDateTime(jsonObject.getString("day"));
            data.setDate(DateUtil.formatDate(date));
            data.setMinute(DateUtil.formatTime(date));
            data.setPrice(jsonObject.getBigDecimal("close"));
            data.setTradeNum(jsonObject.getBigDecimal("volume"));
            list.add(data);
        }
        return list;

    }

    public static List<StockDayData> getHistoryData(String code, String beginDate, String endDate) {
        Date begin = DateUtil.parseDate(beginDate);
        Date end = DateUtil.parseDate(endDate);
        Date tempBegin = begin;
        Date tempEnd = DateUtil.offsetDay(begin, 1000);
        List<StockDayData> stockDayDataList = new ArrayList<>();
        boolean endFlag = false;
        for (int i = 0; i < 10; i++) {
            if (tempEnd.after(end)) {
                tempEnd = end;
                endFlag = true;
            }
            List<StockDayData> list = SinaStockUtils.getHistoryData(code, tempBegin, tempEnd);
            if (CollectionUtils.isNotEmpty(list)) {
                stockDayDataList.addAll(list);
            }
            //拉取3年的股票信息
            tempBegin = DateUtil.offsetDay(tempEnd, 1);
            tempEnd = DateUtil.offsetDay(tempEnd, 1000);
            //完结退出
            if (endFlag) {
                break;
            }
        }
        String s = CandleDataBuilder.dayDataToCandle(stockDayDataList);
        //log.info("length:{},content:{}", s.length(), s);
        return stockDayDataList;
    }

    public static int getDateCount(List<StockDayData> stockDayDataList, String beginDate, String endDate) {
        stockDayDataList = getStockDayDataListByDateRange(stockDayDataList, beginDate, endDate);
        return stockDayDataList.size();
    }

    public static BigDecimal getAveragePrice(List<StockDayData> stockDayDataList) {
        BigDecimal price = new BigDecimal(0);
        for (StockDayData stockDayData : stockDayDataList) {
            price = price.add(stockDayData.getClosePrice());
        }
        return price.divide(new BigDecimal(stockDayDataList.size()), RoundingMode.CEILING).setScale(3,
            RoundingMode.HALF_UP);
    }

    public static BigDecimal getAveragePrice(StockDayData data, String period) {
        return data.getAvarage().getBigDecimal(period);
    }

    public static BigDecimal getAveragePrice(StockDayData data, int period) {
        return data.getAvarage().getBigDecimal(period + "");
    }

    public static void setStockQuota(StockDayData data, String key, Object value) {
        JSONObject quota = data.getQuota();
        if (Objects.isNull(quota)) {
            quota = new JSONObject();
            data.setQuota(quota);
        }
        quota.put(key, value);
    }

    public static <T> T getStockQuota(StockDayData data, String key) {
        if (Objects.isNull(data)) {
            return null;
        }
        JSONObject quota = data.getQuota();
        if (Objects.isNull(quota)) {
            return null;
        }
        return (T)quota.get(key);
    }

    /**
     * 获取布林线
     *
     * @param data
     * @param level
     * @return
     */
    public static BollingerData getBollingerBand(StockDayData data, String level) {
        return data.getBollingerBand();

    }

    public static StockDayData getRealtimeStockDataList(String code) {
        return getRealtimeStockDataList(Lists.newArrayList(code)).get(0);
    }

    /**
     * 获取今日实时数据
     *
     * @param codes
     * @return
     */
    public static List<StockDayData> getRealtimeStockDataList(List<String> codes) {
        String code = StringUtils.join(codes, ",");
        String url = "http://qt.gtimg.cn/q=%s";
        url = String.format(url, code);
        String body = HttpClientUtils.get(url);
        String[] list = body.split(";");
        List<StockDayData> stockDayDataList = new ArrayList<>();
        for (String content : list) {
            String[] array = content.split("~");
            if (array.length < 30) {
                continue;
            }
            StockDayData stockDayData = new StockDayData();
            String datetime = array[30];
            Date date = DateUtil.parse(datetime, PURE_DATETIME_PATTERN);
            stockDayData.setCode(array[0].split("=")[0].substring(2).replaceAll("_", ""));
            stockDayData.setDate(DateUtil.formatDate(date));
            stockDayData.setDatetime(DateUtil.formatDateTime(date));
            stockDayData.setOpenPrice(new BigDecimal(array[5]));
            stockDayData.setClosePrice(new BigDecimal(array[3]));
            stockDayData.setMaxPrice(new BigDecimal(array[41]));
            stockDayData.setMinPrice(new BigDecimal(array[42]));
            stockDayData.setTradeNum(new Integer(array[6]));
            //停牌时，开盘价/=当前价
            if (BigDecimalUtils.eq(stockDayData.getOpenPrice(), BigDecimal.ZERO)) {
                stockDayData.setOpenPrice(stockDayData.getClosePrice());
                stockDayData.setMaxPrice(stockDayData.getClosePrice());
                stockDayData.setMinPrice(stockDayData.getClosePrice());
                stockDayData.setTradeNum(1);
            }
            stockDayDataList.add(stockDayData);
        }
        return stockDayDataList;
    }

    public static List<StockMinuteData> getRealtimeMinuteData(String code) {
        String URL = "https://web.ifzq.gtimg.cn/appstock/app/minute/query?code=%s";
        String url = String.format(URL, code);
        String body = HttpClientUtils.postJSON(url, new JSONObject());
        //HttpHeaders headers = new HttpHeaders();
        //HttpEntity entity = new HttpEntity<>(headers);
        //headers.setContentType(MediaType.APPLICATION_JSON);
        //ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
        //String body = response.getBody().toString();
        JSONObject jsonObject = JSON.parseObject(body);
        if (!jsonObject.getString("code").equals("0")) {
            log.error("getRealtimeMinuteData response error:" + body);
            return null;
        }
        JSONArray jsonArray = jsonObject.getJSONObject("data")
            .getJSONObject(code).getJSONObject("data")
            .getJSONArray("data");
        if (CollectionUtils.isEmpty(jsonArray)) {
            return null;
        }
        String date = DateUtil.formatDate(new Date());
        List<StockMinuteData> list = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            String content = jsonArray.getString(i);
            String[] array = content.split(" ");
            StockMinuteData data = new StockMinuteData();
            data.setDate(date);
            data.setMinute(array[0]);
            data.setPrice(new BigDecimal(array[1]));
            data.setTradeNum(new BigDecimal(array[2]));
            data.setTradeAmount(new BigDecimal(array[3]));
            list.add(data);
        }
        return list;
    }

    /**
     * 整体分析股票数据
     *
     * @param code
     * @param stockDayDataList
     * @return
     */
    public static StockAnalasysData analasysData(String code, List<StockDayData> stockDayDataList) {
        StockAnalasysData analasysData = new StockAnalasysData();
        analasysData.setCode(code);
        analasysData.setDays(stockDayDataList.size());
        ScoreData amplitudeCount = new ScoreData();
        ScoreData upData = new ScoreData();
        ScoreData downData = new ScoreData();
        analasysData.setAmplitudeCount(amplitudeCount);
        analasysData.setUpData(upData);
        analasysData.setDownData(downData);
        BigDecimal yesterdayPrice = stockDayDataList.get(0).getOpenPrice();
        BigDecimal yesterdayMaxPrice = stockDayDataList.get(0).getMaxPrice();
        BigDecimal yesterdayMinPrice = stockDayDataList.get(0).getMinPrice();
        int upCount = 0;
        int downCount = 0;
        int openUpDeviateYesterdayCount = 0;
        int openDownDeviateYesterdayCount = 0;
        int rangeDeviateYesterdayCount = 0;
        int maxCloseCount = 0;
        int minCloseCount = 0;
        int maxOpenCount = 0;
        int minOpenCount = 0;
        int index = 0;
        List<String> openUpDeviateDate = new ArrayList<>();
        List<String> openDownDeviateDate = new ArrayList<>();
        List<String> rangeDeviateDate = new ArrayList<>();
        for (StockDayData data : stockDayDataList) {
            //振幅
            int amplitude = data.getMaxPrice().subtract(data.getMinPrice()).multiply(new BigDecimal(100)).intValue();
            amplitudeCount.addScoreCount(amplitude);
            BigDecimal closePrice = data.getClosePrice();
            BigDecimal openPrice = data.getOpenPrice();

            //上涨
            if (closePrice.compareTo(yesterdayPrice) > 0) {
                int upScore = closePrice.subtract(yesterdayPrice).multiply(new BigDecimal(100)).intValue();
                upData.addScoreCount(upScore);
                upCount++;
            } else if (closePrice.compareTo(yesterdayPrice) < 0) {
                //下跌
                int downScore = yesterdayPrice.subtract(closePrice).multiply(new BigDecimal(100)).intValue();
                downData.addScoreCount(downScore);
                downCount++;

            }
            if (data.getMaxPrice().compareTo(openPrice) == 0) {
                maxOpenCount++;
            }
            if (data.getMaxPrice().compareTo(closePrice) == 0) {
                maxCloseCount++;
            }
            if (data.getMinPrice().compareTo(openPrice) == 0) {
                minOpenCount++;
            }
            if (data.getMinPrice().compareTo(closePrice) == 0) {
                minCloseCount++;
            }
            //偏离振幅
            if (openPrice.compareTo(yesterdayMaxPrice) > 0) {
                openUpDeviateYesterdayCount++;
                openUpDeviateDate.add(data.getDate());
            }
            if (openPrice.compareTo(yesterdayMinPrice) < 0) {
                openDownDeviateYesterdayCount++;
                openDownDeviateDate.add(data.getDate());
            }
            //振幅偏离
            if (data.getMinPrice().compareTo(yesterdayMaxPrice) > 0 || data.getMaxPrice().compareTo(yesterdayMinPrice)
                < 0) {
                rangeDeviateYesterdayCount++;
                rangeDeviateDate.add(data.getDate());
            }

            yesterdayPrice = closePrice;
            yesterdayMaxPrice = data.getMaxPrice();
            yesterdayMinPrice = data.getMinPrice();
            index++;
        }
        amplitudeCount.caculate();
        upData.caculate();
        downData.caculate();
        analasysData.setUpCount(upCount);
        analasysData.setDownCount(downCount);
        analasysData.setOpenUpDeviateYesterdayCount(openUpDeviateYesterdayCount);
        analasysData.setOpenDownDeviateYesterdayCount(openDownDeviateYesterdayCount);
        analasysData.setRangeDeviateYesterdayCount(rangeDeviateYesterdayCount);
        analasysData.setOpenUpDeviateDate(openUpDeviateDate);
        analasysData.setOpenDownDeviateDate(openDownDeviateDate);
        analasysData.setRangeDeviateDate(rangeDeviateDate);
        analasysData.setMaxOpenCount(maxOpenCount);
        analasysData.setMinOpenCount(minOpenCount);
        analasysData.setMaxCloseCount(maxCloseCount);
        analasysData.setMinCloseCount(minCloseCount);
        return analasysData;
    }

    public static boolean isFirstLimitUp(StockDayData data, List<StockDayData> stockDayDataList, int size) {
        int beforeLimitUpCount = getBeforeLimitUpCount(data, stockDayDataList, size);
        return beforeLimitUpCount == 1;
    }

    public static int getBeforeLimitUpCount(StockDayData data, List<StockDayData> stockDayDataList, int size) {
        if (!isLimitUp(data)) {
            return 0;
        }
        stockDayDataList = StockUtils.getStockDayDataListBeforeDate(stockDayDataList, data.getDate(), size);
        int limitUpCount = 1;
        for (int i = 0; i < stockDayDataList.size(); i++) {
            StockDayData stockDayData = stockDayDataList.get(i);
            if (isLimitUp(stockDayData)) {
                limitUpCount++;
            }
        }
        return limitUpCount;
    }

    /**
     * 是否涨停板
     *
     * @param data
     * @return
     */
    public static boolean isLimitUp(StockDayData data) {
        //最高价和收盘价差过2分钱，就不算涨停
        BigDecimal priceRange = BigDecimalUtils.subtract(data.getClosePrice(), data.getMaxPrice());
        if (BigDecimalUtils.isGe(priceRange, new BigDecimal(0.02))) {
            return false;
        }
        return BigDecimalUtils.isGe(data.getRate(), new BigDecimal(9.6))
            && BigDecimalUtils.isLe(data.getRate(), new BigDecimal(10.5));
    }

    public static boolean isLimitDown(StockDayData data) {
        BigDecimal range = data.getMinPrice().subtract(data.getOpenPrice()).abs();
        BigDecimal rate = BigDecimalUtils.subStractAndDividePrecent(range, data.getClosePrice());
        return BigDecimalUtils.isLe(data.getRate(), new BigDecimal(-9.7)) && BigDecimalUtils.isGt(data.getRate(),
            new BigDecimal(-12)) && BigDecimalUtils.isLt(rate, new BigDecimal(0.3));
    }

    public static boolean isOneLineStock(StockDayData data) {
        BigDecimal openPrice = data.getOpenPrice();
        BigDecimal closePrice = data.getClosePrice();
        BigDecimal range = BigDecimalUtils.subtract(closePrice, openPrice).abs();
        BigDecimal rate = BigDecimalUtils.divideToPrecent(range, openPrice);
        if (BigDecimalUtils.isLt(rate, new BigDecimal(0.5))) {
            return true;
        }
        return false;
    }

    /**
     * 计算上影线的百分比
     *
     * @param data
     * @return
     */
    public static BigDecimal caculateUpLineRate(StockDayData data) {
        BigDecimal upPrice = BigDecimalUtils.isGe(data.getOpenPrice(), data.getClosePrice()) ? data.getOpenPrice()
            : data.getClosePrice();
        return BigDecimalUtils.subStractAndDividePrecent(data.getMaxPrice(), upPrice);
    }

    /**
     * 计算下影线的百分比
     *
     * @param data
     * @return
     */
    public static BigDecimal caculateDownLineRate(StockDayData data) {
        BigDecimal downPrice = BigDecimalUtils.isGe(data.getOpenPrice(), data.getClosePrice()) ? data.getClosePrice()
            : data.getOpenPrice();
        return BigDecimalUtils.subStractAndDividePrecent(downPrice, data.getMinPrice());
    }

    /**
     * 计算振幅
     *
     * @param data
     * @return
     */
    public static BigDecimal caculateRangeRate(StockDayData data) {
        BigDecimal upPrice = BigDecimalUtils.isGe(data.getOpenPrice(), data.getClosePrice()) ? data.getOpenPrice()
            : data.getClosePrice();
        BigDecimal downPrice = BigDecimalUtils.isGe(data.getOpenPrice(), data.getClosePrice()) ? data.getClosePrice()
            : data.getClosePrice();
        return BigDecimalUtils.subStractAndDividePrecent(upPrice, downPrice);
    }

    /**
     * 获取连板数量
     *
     * @param stockDayDataList
     * @return
     */
    public static int getMultiLimitUpCount(List<StockDayData> stockDayDataList) {
        int count = 0;
        int limitUpCount = 0;
        for (int i = 0; i < stockDayDataList.size(); i++) {
            StockDayData data = stockDayDataList.get(i);
            if (isLimitUp(data)) {
                limitUpCount++;
            } else {
                if (limitUpCount >= count) {
                    count = limitUpCount;
                }
                limitUpCount = 0;
            }
        }
        return count;
    }

    /**
     * 获取涨停板数量
     *
     * @param stockDayDataList
     * @return
     */
    public static int getLimitUpCount(List<StockDayData> stockDayDataList) {
        int limitUpCount = 0;
        for (int i = 0; i < stockDayDataList.size(); i++) {
            StockDayData data = stockDayDataList.get(i);
            if (isLimitUp(data)) {
                limitUpCount++;
            }
        }
        return limitUpCount;
    }

    public static void initStock(List<Stock> stockList) {
        for (Stock stock : stockList) {
            STOCK_MAP.put(stock.getCode(), stock);
            //添加二级行业黑名单
            if (StockSecondIndustryEnums.isBlackIndustry(stock.getSecondIndustry())) {
                SECOND_INDUSTRY_BLACK_LIST.add(stock.getCode());
            }
        }
    }

    public static Stock getStock(String code) {
        return STOCK_MAP.get(code);
    }
}

